package org.NooLab.texx;

import java.util.ArrayList;
import java.util.Map;




import org.NooLab.randomgraph.RGraphResultsProvidingEventSinkIntf;
import org.NooLab.randomgraph.RandomGraph;
import org.NooLab.randomgraph.RandomGraphFactory;
import org.NooLab.randomgraph.RandomGraphIntf;
import org.NooLab.randomgraph.SmallContextReplacementIntf;
import org.NooLab.randomgraph.app.IniProperties;
import org.NooLab.randomgraph.app.RGraphPrepare;
import org.NooLab.randomgraph.app.RGraphPrepareIntf;
import org.NooLab.randomgraph.components.TextCleanerIntf;
import org.NooLab.randomgraph.interfaces.RGraphPropertiesIntf;
import org.NooLab.randomgraph.properties.RGraphProperties;
import org.NooLab.somquery.SomQueryIntf;
import org.NooLab.structures.randomgraph.GuidObject;
import org.NooLab.structures.randomgraph.ParticledText;
import org.NooLab.structures.randomgraph.RGraphPropertiesDefaultIntf;
import org.NooLab.structures.texx.plugg.algo.intf.AlgoAssignatorIntf;
import org.NooLab.structures.texx.plugg.algo.intf.AlgorithmIntf;
import org.NooLab.structures.texx.plugg.algo.intf.TextObject;
import org.NooLab.texx.components.AlgorithmsProvider;
import org.NooLab.texx.components.AlgorithmsProviderIntf;
import org.NooLab.texx.components.WorkDataObject;
import org.NooLab.texx.components.textprocs.SmallContextReplacement;
import org.NooLab.texx.components.textprocs.TextCleaner;
import org.NooLab.texx.components.textprocs.WordCleaner;
import org.NooLab.texx.components.textprocs.variants.PoSTagger;
import org.NooLab.texx.properties.TexxProperties;
import org.NooLab.texx.storage.FileStore;
import org.NooLab.texx.storage.TexxDataBase;
import org.NooLab.texx.storage.TexxFileFlow;
import org.NooLab.utilities.datatypes.SerialMap;
import org.NooLab.utilities.datatypes.SerialMapItem;
import org.NooLab.utilities.datatypes.SerialMapItemIntf;
import org.NooLab.utilities.files.DFutils;
import org.NooLab.utilities.logging.PrintLog;
import org.NooLab.utilities.net.GUID;
import org.NooLab.utilities.objects.StringedObjects;





public class MethodDispatcher 
								implements 
											RGraphResultsProvidingEventSinkIntf{
											//,SmallContextReplacementIntf{

	
	Texx texx;
	
	TexxTask texxTask;
	TexxFactory texxFactory;
	TexxDataBase  texxDataBase ;
	
	TexxProcessIntf texxProcess;
	
	TexxProperties texxProperties ;
	
	int activeProcessesCount = 0;
	 
	int rgIntermediateResultsType = -1;
	ParticledText pText = null;
	int clientResultsProviding = -1;
	int rgVariantProcessing = 0;
	
	TexxPluginSettingsIntf pluginSettings;
	MethodDispatcher medis;
	
	ArrayList<Long> finishedWorkDataObjects = new ArrayList<Long>();
	ArrayList<String> completedWorkerProcess = new ArrayList<String>();
	
	private WorkDataObject _workDataObj;
	WorkerProcess workerProcess;
	// ArrayList<WorkerProcess> processes ;
	private PrintLog out = new PrintLog(2,false);
	public StringedObjects strobj = new StringedObjects();
	
	 
	// =========================================================================
	public MethodDispatcher(Texx txx, TexxTask txxtask, TexxFactory txxfactory) {
		// 
		texx = txx ; 
		texxTask = txxtask ; 
		texxFactory = txxfactory ;
		
		texxDataBase = texx.txxDataBase ;
		texxProperties = texxFactory.texxProperties ;
		
		medis = this;
		
		getOut().setPrefix("[TEXX-M]");
		prepare();
	}
	// =========================================================================
	
	
	public void checkConsistencyOfRequest() throws Exception {

		
		boolean requestIsOk = true;
		String msgStr="" ,tvLabel="";
		int tvindex = -1 ; 
		
		
	
		// 1. do we work in somType = mono?
		if (texxProperties.getWorkerType() != TexxProperties._WORKER_TYPE_DEFAULT){
			requestIsOk = false;
			msgStr = "The type of som (associative storage) does not match the type of the process (Optimizer)." ;
		}
		
		if (requestIsOk){
		// 2. does the target variable exist ? and are values >0 ? how many MV in TV column

			
			if ((tvindex<0) && (tvLabel.length()==0)){
				requestIsOk = false;
				msgStr = "type of process is 'optimization', yet, no target variable definition could be found." ;
			}
		}
		if (requestIsOk){
			
			if ((tvindex<0) ){
				requestIsOk = false;
				msgStr = "mismatch in target veriable pointers.";
			}
		}
	
		if (requestIsOk){
			if (tvindex<0){
				requestIsOk = false;
				msgStr = "no data found in target column of table containing normalized data." ;
			}
		}
		
		if (requestIsOk){
			if (tvindex<0){
				requestIsOk = false;
				msgStr = "No target group has been defined, thus no modeling is possible." ;	
			}
		}
		
	
		if (requestIsOk){
		// 3. will the definition of the target groups yield any case count >3 
		
		}
		
		if (requestIsOk == false){
			throw(new Exception("Request for running the chosen method is not consistent: "+ msgStr));
		}

		
	}

	

	private void prepare() {
		
		int z=0;
		
		// if enforced then somDataObj.clear();
		
		
		
		try {

			pluginSettings = texxProperties.getPluginSettings();
			
			AlgorithmsProvider algorithmsProvider = new AlgorithmsProvider (texxProperties);
			z = algorithmsProvider.createAlgoObjects( AlgorithmIntf._ALGOTYPE_ASSIGNATOR );
		
			if (z>0){
				pluginSettings.addAlgorithmsProvider(algorithmsProvider) ;
			}else{
				return ;
			}

			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	
	
	
	public void perform( WorkDataObject  workDataObj) {

		workerProcess = new WorkerProcess( this, 0); 
		workerProcess.setDataObj( new WorkDataObject(workDataObj, true) ) ;
		workerProcess.start() ;
		 
	}
	
	
	public WorkerProcess getWorkerProcess() {
		return  new WorkerProcess( this, 0); 
	}
	
	/*
	 * this is a  ; 
	 * @see org.NooLab.randomgraph.RGraphResultsProvidingEventSinkIntf#setResultsAvailable(int, org.NooLab.randomgraph.types.ParticledText)
	 */
	@Override
	public int setResultsAvailable( Object refObj, int type, ParticledText ptext) {
		/*
		 * 
		 * here we should NOT do any processing, since then processes could overlap
		 * we need to route it directly to their own object-capsules
		 * 
		 */
		
		int response = (new ClientInformerSink( refObj, type, ptext )).handleAnnouncement();
		
		return response;
	}
	
	
	@Override
	public int getResponseValue() {
		   
		// this global indicator will be set =0 (==RG:proceed!)  
		// after the processing has been finished
		return clientResultsProviding;
	}
	
	
	// ........................................................................
	/**
	 * 
	 * this class performs the analysis for the provided source 
	 *
	 * each instance of the workerprocess gets its own rgProperties and its own rgFactory !!
	 *
	 */
	class WorkerProcess implements Runnable, RGraphPrepareIntf{

		WorkDataObject  workDataObj_ ; 
		
		SmallContextReplacement replacer ;
		TextCleaner textCleaner;
		WordCleaner wordcleaner ;
		SomQuery somquery;
		
		String processGuid = ""; 
		// will not be used in persistence, just for tracking the processes and multi-threads
		
		RGraphPrepareIntf rpi ;
		RGraphPrepare rp;
		RandomGraphFactory rgFactory;
		RGraphPropertiesDefaultIntf rgProperties;
		
		private int optimizerProcIndex;
		private MethodDispatcher medisParent;
		
		ArrayList<ArrayList<?>> assignates;	
		
		boolean isRunning=false;
		Thread medisThrd;

		
		
		public WorkerProcess( MethodDispatcher medis, int index){
			
			optimizerProcIndex = index;
			this.medisParent = medis;
			
			
			processGuid = GUID.randomvalue() ;
			
			medisThrd = new Thread(this,"medisProcThrd-"+index) ;
		}

		
		public void setDataObj(WorkDataObject  workObj) {
			
			workDataObj_ = workObj ;
		}


		@Override
		public void issueUserbreak() {
			// TODO Auto-generated method stub
			
		}


		@Override
		public RGraphPropertiesDefaultIntf getProperties() {
			return rgProperties;
		}


		@Override
		public void prepareRGrapher() {

			rgProperties = rpi.getProperties() ;
			rgProperties = new RGraphProperties();
			
			rgProperties.setInitializationOK(true);
			
					String dir = IniProperties.fluidSomProjectBasePath ;
					// D:/data/iTexx/Texx/
					// D:/data/iTexx/Rgraph/
					if ((dir.length()==0) || (DFutils.folderExists(dir)==false)){
						dir = texxProperties.getPersistenceSettings().getPathToSomFluidSystemRootDir() ;
					}
					dir = DFutils.getParentDir(dir,1);
					dir = DFutils.createPath(dir, "RGraph") ;
			rgProperties.setSystemRootDir( dir ) ;
			rgProperties.setProjectNameByInstance( RandomGraphFactory._INSTANCE_TYPE_TEXT );
			
			String systemroot = rgProperties.getSystemRootDir();
			
			if ( texxProperties.getApplicationContext().startsWith("itexx") ){
				rgProperties.setSystemRootDir( texxProperties.getSystemRootDir()) ;	
				// e.g.: D:/data/iTexx/
			}
			
			rgProperties.setApplicationContext( texxProperties.getApplicationContext()) ;
			
			try {

				rgFactory = RandomGraphFactory.get(rgProperties);
				
				rgFactory.setProcessId( processGuid );
			} catch (Exception e) {
				e.printStackTrace();
			}

			// rgProperties.save();
		}

		class WorkTaskRouter{
			
			

			public WorkTaskRouter(){
				
			}
			
			public void perform( WorkDataObject _workDataObj_) throws Exception{
			

				long _doc_id=0;
				TextObject textObj = new TextObject ();
				String wpi = this.toString();
				
				
				
				// workDataObj_ = (WorkDataObject)texx.getSrcLoader().load( workDataObj_.getSourceUrl() );
				
				String text = workDataObj_.getRawPlainText() ;
				
				if ((text==null) || (text.trim().length()<=3)){
					throw(new Exception("\n\nText before <WordCleaner()> was empty...\n" +
							            "filename was : "+ workDataObj_.getSourceUrl()+"\n"+
							            "make sure that Apache Tika is reachable, e.g. through NooLabTikaServer!\n"));
				}
				textCleaner = new TextCleaner() ; 
				// e.g. removing pdf crap...  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
				
				
				textObj.setText(text);

				/* no static initialization !!!! this would overwrite
				RandomGraphFactory.setStartupLocations( RandomGraphFactory._INSTANCE_TYPE_TEXT,
														"/data/iTexx/RGraph/"); //defaultLocationPath);
				*/
				rpi = RGraphPrepare.getInstance();
				rp = (RGraphPrepare)RGraphPrepare.getInstance();
				prepareRGrapher();
				
				// later, this has to be taken from config file
				// rgProperties.setLengthPrimaryVector() ; or ... is synonym 
				rgProperties.setLengthItemFingerprints(30) ; // default 10
				rgProperties.setLengthResultVector(80) ;	 // default 80
				rgProperties.setLengthNeighborhood(7) ;      // default 5 ;
				rgProperties.setIsPOSsensitive(true)   ;
				rgProperties.setIsLeftEmphasis(1)   ;        // 0 = symmetric, {1..10}
				
				rgProperties.setColumnPrefix("rgr_"); // TODO: in plugin, it comes from the AssignatorIntf
				
				// some of the variants require an extra pass through, some are just activated,
				rgProperties.addVariant( RGraphPropertiesIntf._RG_VARIANT_SOMM ); // SomStore properties as string = renormalization
				rgProperties.addVariant( RGraphPropertiesIntf._RG_VARIANT_SIM  ); // create version based on "normalized" words (enhancing similarity match)
				rgProperties.setLevelOfWordNormalization(1);	// fingerprints are based on normalized words: without ending, rich replacement table of chars (rich soundex),														      
				rgProperties.addVariant( RGraphPropertiesIntf._RG_VARIANT_POS  ); // PoS tagging
				rgProperties.addVariant( RGraphPropertiesIntf._RG_VARIANT_ACRO ); // expanding acronyms
				rgProperties.addVariant( RGraphPropertiesIntf._RG_VARIANT_SYN  ); // synonyms apply to verbs only !
				rgProperties.setNumberOfConsideredSynonyms(3);
				
				rgFactory.setTextData(text) ;
				
				rgFactory.setClientInformer((RGraphResultsProvidingEventSinkIntf) medisParent) ;
				
				replacer = new SmallContextReplacement( medis );
				rgFactory.setSmallContextReplacer( replacer );
				
				wordcleaner = new WordCleaner();
				rgFactory.setWordCleaner(wordcleaner) ;
				
				
				rgFactory.setTextCleaner( (TextCleanerIntf)textCleaner) ;
				
				somquery = new SomQuery(); // a class inside Texx, 
										   // as a facade (NOT an extension) to the SomQuery in the SomQuery package ... 
				rgFactory.setSomQuery( (SomQueryIntf) somquery); 
					
				
				replacer.preprocessing();
				
				clientResultsProviding = -1;
				
				// now we have to provide the global index and Guid of the provided text
				// we do it with a small object since there could be several
				// the vector is always build using all 
				GuidObject guidObj = new GuidObject();
				

		        // this ID is from docoserv DB !!! replace it by procedure !!
				 
				if ( texxTask.getSourceType()==TexxTaskIntf._TEXXTASK_SOURCE_TYPE_DB){
					// will arrive through rerouted processing via MethodDispatcherServer
					_doc_id = 13841 ;
					_doc_id = workDataObj_.getSourceId() ;
				}
				if ( texxTask.getSourceType()==TexxTaskIntf._TEXXTASK_SOURCE_TYPE_FILE){
					_doc_id = workDataObj_.getTimeStamp() ; // 13841 ;

					// if it is working in file based mode (without docoserv)
			        // we should get it as a hash of the filename

					// getAdHocDocumentID();
					// String.hashCode());
				}
				
				guidObj.setPrimaryGuid("") ;
				guidObj.setPrimaryIndex( _doc_id) ; 
				
				
				     
				rgFactory.setGuidIndices( guidObj );
				
				String fsname="", rgi="";
				
				fsname = workDataObj_.getSourceUrl() ;
				// fsname = DFutils.getName(fsname);
				wpi = wpi.replace("org.NooLab.texx.", "");
				rgi = rgFactory.toString().replace("org.NooLab.randomgraph.", "");
				
				getOut().print(3, "\n... going to call RGraphFactory for document "+fsname+", \n"+
						          "    WorkerProcess instance : "+wpi+", \n"+
						          "    RGraphFactory instance : "+rgi+"\n");
				
				
				rgVariantProcessing = 1;
				
				boolean rB = rgFactory.start();
				if (rB==false){
					throw(new Exception("the RandomGraph sub-processor didn't start properly.\n")) ;
				}
				// it will return only if it has completed its job
				// yet we have also a callback through
				// setResultsAvailable() and getResponseValue()
				// we can restart the RandomGraph stuff for a variant
				// setting rgVariantProcessing > 0 as an id (use a constant...)
				// e.g. taking 2 or three synonyms at random for replacement
				//      or using PoS-tagging of the words
				
				// better?: wait in a waiting thread? 
				while (rgFactory.isFinished()==false){
					getOut().delay(10);
				}
				ArrayList<ArrayList<?>> doctable ;
				doctable = rgFactory.getResults();
				
				getOut().printErr(2,"\nback in MethodDispatcher of Texx!") ;
				
				if (doctable==null){
					getOut().print(2, "results are unexpectedly =null.") ;
					throw(new Exception("Results returned from RandomGraph module are unexpectedly ==null.")) ;
				}else{
					
					getOut().print(2 ,"fixed part of assignates table ("+doctable.get(1).size()+" records): \n"+doctable.get(0).toString() );
					// put this table to a temp file, and collect the temp filename
					// later, we will have to work on the table (adding data) 
					// and combining all tables from the docs touched in this session
					
					
					String doctableEnc = strobj.encode(doctable);
					
					// likewise to lucene/solr then saving the index from there
					String tmpFilename = FileStore.saveEncodedOjectsToFile( "", doctableEnc );
					// store this with the the ID of the source file
					// Stor-Object  TexxFileFlow ...
					TexxFileFlow txxFileFlow;
					
					// this.medisParent.getTexxFactory().getMainModule().
					// randomgraph: 
					//               needs version string into the table, full header
					//               the string array containing wordlabel is null on pos[0] ?? storlabelGuid
					String language = workDataObj_.getDocumentMetaData().getLanguageCode() ;
					
																out.print(2, "storing table of compressed random contexts to data base...");
					// TODO this should be queued !!!
					// get docindex : from doctable (second col = col(1) ) or from resultsDescription ...
					texx.txxDataBase.storeDocTable(doctable,language );
					
					texx.txxDataBase.close();
																out.print(2, "storing table completed."); 
				} // result != null

				workDataObj_.setFinished(true);  // a95d9b2f-2876-4a82-bc59-6be823544ec7
				finishedWorkDataObjects.add( workDataObj_.getSourceId() );
			}
		}
		private void workonTaskinTestMode( ) throws Exception{
						
			
			(new WorkTaskRouter()).perform(workDataObj_);
		}
		
		private void workonTask(){
			
			String algoName;
			AlgoAssignatorIntf assignatorAlgo ; 
			
			getOut().printErr(2, "MethodDispatcher::WorkerProcess::workOnVariableSubset");
		
			
			// 
			getOut().print(2,">>>>>>>>>>>>>> do the evaluation of text into a structured admin from here... \n"+
					    "               (tagging, sentences, sections, indices") ;
			
			/*
			 * for all available transformation algorithms (=extracting properties)
			 * -> these algorithms must be available as plugins, we create an array of values
			 * arranged in a table
			 * 
			 * this table contains just 1 header row and 1 data row 
			 * 
			 * each of the algorithms creates such a table, the short name of the algorithm
			 * serves as prefix of for the column names 
			 * 
			 * The method dispatcher loads the algorithms and maintains a list,
			 * similar to Texx, where the list of readers is maintained
			 */
			
			// inform the digester... txxTask.setWorkResultHandler( workResultHandler  ) ;
			
			AlgorithmsProviderIntf ap = pluginSettings.getAlgorithmsProviderByType( AlgorithmIntf._ALGOTYPE_ASSIGNATOR );
			Map<String,Object> algoMap = ap.getAlgorithMap();
			
			ArrayList<SerialMapItemIntf> adsItems = texxProperties.getPluginSettings().getAlgoDeclarations().getItems();
			SerialMap ads = texxProperties.getPluginSettings().getAlgoDeclarations() ;
			
			ArrayList<String> algoNames = ap.getAlgorithmNames() ;
			
			for (int a=0;a<algoNames.size();a++){
				algoName = algoNames.get(a) ;
				
				SerialMapItem mappedItem = (SerialMapItem)ads.getObject(algoName);
				
				if ((algoMap.containsKey(algoName)) && (mappedItem.getActivationStatus()>=1)){
					assignatorAlgo = (AlgoAssignatorIntf)algoMap.get(algoName) ;	
					
					ArrayList<ArrayList<?>> assignates = executeAlgorithm(assignatorAlgo);
					collectAssignatesPerAlgorithm(assignates) ;
				}
			}// all potential algorithms
			
			
		}
		
		
		@Override
		public void run() {
			boolean hb ;
			String workDataGuid = workDataObj_.getReceipt() ;
			Long sourceid = workDataObj_.getSourceId() ;
			
			out.print(3, "  .......  received receipt (1): "+workDataGuid);
			try {
				
				try {
					hb = texxProperties.getApplicationContext().contentEquals( TexxProperties._APP_CONTEXT_ITEXX) ; 
					if ((hb) || (texxTask.isBatchMode() )) {
						String filename = workDataObj_.getSourceUrl() ;
											getOut().print(2, "... loading : " + filename );
						
						// this creates a new wdo !!!
											
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<						
						workDataObj_ = (WorkDataObject)texx.getSrcLoader().load( workDataObj_.getSourceUrl() );

						
						// workDataObj_ = (WorkDataObject)texx.loadSource(filename);
						
						if (workDataObj_.getRawPlainText().length()<=3){
							
							getOut().printErr(1, "... returning from loading, but it failed or document is empty.");
							throw(new Exception("Loading of document failed."));
							
						}else{
							getOut().print(2, "... loading completed.");
						}
						
						// thus we have to 
						workDataObj_.setReceipt(workDataGuid);
						workDataObj_.setSourceId( sourceid ) ;
					}
				}catch(Exception e){
				}
				
				// workonTask();  "test mode" means, that we do not use plugins 
				workonTaskinTestMode();        // for developing the randomgraph module...
				
				// send workDataGuid back to thread in dispatcherServer;
				completedWorkerProcess.add( workDataGuid );
				// DocumentObserverIntf._STATUS_FILE_HANDLING  -> _STATUS_FILE_DESCRIBED
				
			} catch (Exception e) {
				getOut().printErr(2, e.getMessage() ) ;
				// e.printStackTrace();
			}
			isRunning=false;
		}


		@SuppressWarnings("unchecked")
		public boolean collectAssignatesPerAlgorithm( ArrayList<ArrayList<?>> assignatesPart ) {
			boolean rB=false;
			ArrayList<String> headers,_headers ;
			ArrayList<Double> values , _values;
			

			try{

				if ((assignatesPart==null) || (assignatesPart.size()==0)){
					return rB;
				}
				
				if (assignates==null){
					assignates = new ArrayList<ArrayList<?>>();
					headers  = new ArrayList<String>();
					values   = new ArrayList<Double>();
					
					assignates.add(headers);
					assignates.add(values);
				}
				
				headers  = (ArrayList<String>) assignates.get(0);
				_headers = (ArrayList<String>) assignatesPart.get(0) ;

				values   = (ArrayList<Double>) assignates.get(1);
				_values  = (ArrayList<Double>) assignatesPart.get(1) ;

				
				if ((_headers==null) || (_headers.size()==0) ||
					(_values==null)  || (_values.size()==0) ||
					(_headers.size() !=_values.size())){
					return rB;
				}

				
				headers.addAll( _headers);
				values.addAll( _values);
				rB=true;
				
			}catch(Exception e){
				e.printStackTrace();
			}
			
			return rB;
		}


		private ArrayList<ArrayList<?>> executeAlgorithm(AlgoAssignatorIntf preAlgorithm) {
			
			TextObject textObj;
			ArrayList<ArrayList<?>> assignates = null; // contains 2 lists: (1) <String>, (2) Double
			
			AlgoAssignatorIntf algorithm;
			try{
			
				algorithm = (AlgoAssignatorIntf)preAlgorithm.getClass().newInstance(); 
				
				getOut().print(2, "\nWorkerProcess ("+this.toString()+") running \n"+
						     "workDataObj ("+workDataObj_.toString().replace("org.NooLab.", "")+") and \n"+
						     "algorithm ("+algorithm.toString().replace("org.NooLab.", "")+")  \n"+
						     "are working on document <"+workDataObj_.getSourceUrl()+"> \n"+
						     "which has text length L = "+workDataObj_.getRawPlainText().length()+"  \n\n") ; 
				textObj = new TextObject(); 
				String text = workDataObj_.getRawPlainText() ;
				
				textObj.setText(text);
				
				algorithm.clearText();
				algorithm.setTextValue(textObj) ;
				algorithm.calculate() ;
				
				getOut().delay((int) (2000 + Math.random()*1000));
				
				assignates = algorithm.getAssignates();
				
				getOut().print(2, "assignates: "+assignates.get(0)+", "+assignates.get(1) );
				int n=assignates.size();
				
			}catch(Exception e){
				e.printStackTrace() ;
			}
			
			
			
			return assignates;
		}


		public int start() {
			if ((medisThrd.isAlive()==false) && (isRunning==false)){
				
			}
			isRunning=true;
			medisThrd.start();
			return optimizerProcIndex;
			
		}

		
	}
	class ClientInformerSink {
		int type;
		ParticledText pText;
		Object refObj;
		
		//.................................................
		public ClientInformerSink ( Object refObj, int type, ParticledText ptext){
			this.type = type;
			pText = ptext;
			this.refObj = refObj;
		}
		//.................................................
		
		public int handleAnnouncement() {
			// 
	
			int response=0;
			 
			rgIntermediateResultsType = type;
			
			/*
			 * if we want to process the particles in particled text, 
			 * e.g. in order to create a variant of the basic processing through
			 * acting onto the words before they will be transposed into random graphs,
			 * then we should return a value > 1
			 * 
			 * If we do that, we could perform our processing here
			 */
			getOut().print(3, "intermediate results announced in <MethodDispatcher> ...");
			// - processing, starting in its own thread....  
			// - immediately returning response=8
			// - the randomgraph processor then will wait until we set
			//   clientResultsProviding=0
			if (rgVariantProcessing>0){
				getOut().print(3, "intermediate results accepted, preparing variant processing...");
				(new RgraphVariantProcessing( refObj, rgVariantProcessing, pText)).perform();
				response=8;
				getOut().printErr(3, "returning code for suspending processing in RandomGraph component...");
			}
			/*
			 *  
			 */
			return response;
		}
		
	}
	// ..........................................
	class RgraphVariantProcessing implements Runnable{
		
		Thread rvpThrd;
		ParticledText pText ;
		int rgVariant = -1;
		RandomGraph rgraph ;
		RGraphProperties rgProperties;
		private RandomGraphIntf rgraphi;
		
		
		public RgraphVariantProcessing( Object referenceObj, int rgvariant, ParticledText ptext) {
		
			rvpThrd = new Thread(this,"rvpThrd") ;
			pText = ptext ;
			
			rgraphi = ((RandomGraphIntf)referenceObj);

			// this properties object has been created by the respective WorkerProcess!!
			// it is provided by the RandomGraph Instance, which has been also created there. 
			rgProperties = rgraphi.getRgProperties() ;
			// additional parameters... through further interfaced methods
			
		}

		public void perform() {
			rvpThrd.start();
		}

		private void processingParticeldText(){
			
			getOut().printErr(3, "variant processing is going to be performed...");

			/* these variant calculators act on words as they are available in the list of WordPosition objects,
			 * and on sentences as the are available in the list of sentence objects (RichRawEntity)
			 * 
			 * to these objects they add further results, e.g. to items in sentences the PoS-tags,
			 * or to words things like acronym, synonym, translations
			 * 
			 * These informations are stored in a generic object ArrayList<?> , which "usually" will contain
			 * 
			 * it is then the task of RandomGraph to take this information, to normalize it, and then
			 * - to add it to the descriptive vector before compressing it to the final output, or
			 * - create a new variant vector
			 * 
			 * 
			 * 
			 */
			
			if (rgProperties.isVariantActive( RGraphPropertiesIntf._RG_VARIANT_POS)){
				// also: the general wrapper should use a plugin for each language
				PoSTagger pt = new PoSTagger(pText, rgProperties);
				// the pos tagger also refers to the SomStore in order to enhance the tagging
				// tagging comes as ordinal variable, expressing risk, prob 5 levels
				//   VP5 means it is save to be considered as verb phrase, VP0 it is quite unsafe
				// 
				pt.perform();
				pt.clear(); pt=null;
			}

			if (rgProperties.isVariantActive( RGraphPropertiesIntf._RG_VARIANT_SYN)){
				SynonymHandler syn = new SynonymHandler(pText, rgProperties);
				syn.perform();
				syn.clear(); syn=null;
			}

			if (rgProperties.isVariantActive( RGraphPropertiesIntf._RG_VARIANT_ACRO)){
				AcronymHandler acro = new AcronymHandler(pText, rgProperties);
				acro.perform();
				acro.clear(); acro=null;
			}
			if (rgProperties.isVariantActive( RGraphPropertiesIntf._RG_VARIANT_TRANS)){
				TranslationHandler trans = new TranslationHandler(pText, rgProperties);
				trans.perform();
				trans.clear(); trans=null;
			}
			

			RandomGraphVariants rgv = new RandomGraphVariants( medis, pText, rgVariant) ;
			int z=0;
			while (z<1){
				getOut().delay(30);  // DEBUG ONLY !!!
				getOut().print(2, "variant is being processed (sim.) ... "+(int)(((double)z/(double)3)*100.0)+"%");
				z++;
			}
			clientResultsProviding = 0;
		}
		
		@Override
		public void run() {
			 
			processingParticeldText(); 
		}
		
	}
	// ..........................................
	
	
	public void setWorkDataObject(WorkDataObject workdataobj) {
		
		_workDataObj = workdataobj;
	}


	public int getActiveProcessesCount() {
		return activeProcessesCount;
	}


	public void setActiveProcessesCount(int activeProcessesCount) {
		this.activeProcessesCount = activeProcessesCount;
	}


	public TexxFactory getTexxFactory() {
		return texxFactory;
	}


	public WorkDataObject getWorkDataObj() {
		return _workDataObj;
	}


	public ArrayList<String> getCompletedWorkerProcess() {
		return completedWorkerProcess;
	}


	public void setOut(PrintLog out) {
		this.out = out;
	}


	public PrintLog getOut() {
		return out;
	}



		

}
